﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Globalization;
using System.Windows.Forms;
using System.Threading;

namespace Barbar.UrlGuard.BL.Concrete {
  internal class Translator : ITranslator {
    private Hashtable m_Languages = new Hashtable(10);

    private class Localizator : ILocalizator {
      private ITranslator m_Translator;
      private int m_LanguageID;

      public Localizator(int languageID, ITranslator translator) {
        if (translator == null)
          throw new ArgumentNullException("translator");

        m_Translator = translator;
        m_LanguageID = languageID;
      }

      #region ILocalizator Members

      public string Translate(string key) {
        return m_Translator.Translate(m_LanguageID, key);
      }

      #endregion
    }

    public Translator(IMessageCollectionProvider messagesProvider) {
      if (messagesProvider == null)
        throw new ArgumentNullException("messagesProvider");

      foreach (MessageCollection collection in messagesProvider.GetMessageCollections()) {
        int languageID = CultureInfo.GetCultureInfo(collection.LanguageCode).LCID;
        if (m_Languages.ContainsKey(languageID))
          throw new Exception(string.Format(CultureInfo.InvariantCulture, "Duplicate language code found : {0}.", collection.LanguageCode));

        Hashtable messagesDictionary = new Hashtable(collection.Count * 3);
        m_Languages.Add(languageID, messagesDictionary);
        foreach (Message message in collection) {
          messagesDictionary.Add(message.Key, message.Value);
        }
      }
    }

    #region ITranslator Members

    public string Translate(int languageID, string key) {
      Hashtable messageDictionary = (Hashtable)m_Languages[languageID];
      if (messageDictionary == null)
        throw new Exception(string.Format(CultureInfo.InvariantCulture, "Language #{0} not valid.", languageID));

      string value = (string)messageDictionary[key];
      return value ?? key;
    }

    public void Localize(Control rootControl) {
      if (rootControl == null)
        throw new ArgumentNullException("rootControl");

      Stack<Control> stack = new Stack<Control>();
      stack.Push(rootControl);

      int languageID = Thread.CurrentThread.CurrentCulture.LCID;
      Localizator localizator = new Localizator(languageID, this);

      while (stack.Count != 0) {
        Control currentControl = stack.Pop();
        foreach (Control childControl in currentControl.Controls) {
          stack.Push(childControl);
        }
        ILocalizable localizableControl = currentControl as ILocalizable;
        if (localizableControl != null) {
          localizableControl.Localize(localizator);
        }
      }
    }

    public IEnumerable<CultureInfo> GetLanguagesAvailable() {
      foreach (int languageID in m_Languages.Keys) {
        yield return new CultureInfo(languageID);
      }
    }

    #endregion
  }
}
